# -*- coding: utf-8 -*-..,
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv 
from openerp.tools.translate import _
from openerp import tools 

import pytz 
import crea8s_followup.tzlocal 
from crea8s_followup.tzlocal import get_localzone # $ pip install tzlocal
import datetime 
import time 
from datetime import timedelta
# from datetime import datetime

# ?????
#  only can be saving, afterchoosing "Active..."  => ???? 
#
# 
class crea8s_followup_send(osv.osv): # === account_followup_print    
    def _get_followup(self, cr, uid, context=None):
        if context is None:
            context = {}
#         if context.get('active_model', 'ir.ui.menu') == 'crea8s.followup':
#             return context.get('active_id', False)
        company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
        followp_id = self.pool.get('crea8s.followup').search(cr, uid, [('company_id', '=', company_id)], context=context)
        return followp_id and followp_id[0] or False


    _name = "crea8s.followup.send"
    _description = 'crea8s_followup_send...'
    _columns = {
        
        'name': fields.text('Name ....'),
		'date': fields.date('Follow-up Sending Date', required=True, help="This field allow you to select a forecast date to plan your follow-ups"),
        'followup_id': fields.many2one('crea8s.followup', 'Follow-Up', required=True, readonly = True),
        'company_id': fields.related('followup_id', 'company_id', type='many2one', string='Company ID',
                                    relation='res.company', store=True, readonly=True),
        'email_conf': fields.boolean('Send Email Confirmation'),
        'email_subject': fields.char('Email Subject', size=64),
        'partner_lang': fields.boolean('Send Email in Partner Language',
                                    help='Do not change message text, if you want to send email in partner language, or configure from company'), #???
        'email_body': fields.text('Email Body'),
# 'state': fields.selection([('draft','Draft'),
# ('confirmed','Confirmed')],'State',required=True,readonly=True)
    }
       
    strFormatTime = '%Y-%m-%d %H:%M:%S %Z'    
    _defaults = {
        'date': time.strftime('%Y-%m-%d'), #??? lambda *a: time.strftime('%Y-%m-%d')
        'followup_id': _get_followup,
        'email_body': "",
        'email_subject': _('Invoices Reminder'), 
        'partner_lang': True, #???
    } 
    
    
    def update_partner(self, cr, uid, ids, dictAMLs, arrPartners, dDate, context={}):
        #+ dicPartnerFoll: {'to_update': {'46': {'partner_id': 50001, 'level': 1}, '21': {'partner_id': 50001, 'level': 1}}, 'partner_ids': [50001]}

        for key, value in dictAMLs.items(): # loop a list. ; enumerate(arrAMLs)  | dictAMLs.items()
           if value['partner_id'] in arrPartners:
               self.pool.get('account.move.line').write(cr, uid, [int(key)], {'crea8s_followup_line_id': value['level'], 'crea8s_followup_date': dDate})
           
        return True
    
    def process_partner (self, cr, uid, partner_ids, data, context={}):
        partner_obj = self.pool.get('res.partner')
        partner_ids_to_print = []
        nbmanuals = 0
        manuals = {} 
        nbmails = 0
        nbunknownmails = 0
        nbprints = 0
        resulttext = " "
        for partner in self.pool.get('crea8s.followup.partner.view').browse(cr, uid, partner_ids, context=context):
#             if partner.max_followup_detail_id.manual_action:
#                 partner_obj.do_partner_manual_action(cr, uid, [partner.partner_id.id], context=context)
#                 nbmanuals = nbmanuals + 1
#                 key = partner.partner_id.crea8s_payment_responsible_id.name or _("Anybody") #aaa
#                 if not key in manuals.keys():
#                     manuals[key]= 1
#                 else:
#                     manuals[key] = manuals[key] + 1
            if partner.max_followup_detail_id.send_an_email:
                nbunknownmails += partner_obj.do_partner_mail(cr, uid, [partner.partner_id.id], context=context)
                nbmails += 1
            if partner.max_followup_detail_id.send_a_letter:
                partner_ids_to_print.append(partner.id)
                nbprints += 1
                message = _("Follow-up letter of ") + "<I> " + partner.partner_id.crea8s_latest_followup_level_id_without_lit.name + "</I>" + _(" will be sent")  
                partner_obj.message_post(cr, uid, [partner.partner_id.id], body=message, context=context)
        if nbunknownmails == 0:
            resulttext += str(nbmails) + _(" email(s) sent")
        else:
            resulttext += str(nbmails) + _(" email(s) should have been sent, but ") + str(nbunknownmails) + _(" had unknown email address(es)") + "\n <BR/> "
        resulttext += "<BR/>" + str(nbprints) + _(" letter(s) in report") + " \n <BR/>" + str(nbmanuals) + _(" manual action(s) assigned:")
        needprinting = False
        if nbprints > 0:
            needprinting = True
        resulttext += "<p align=\"center\">"
        for item in manuals:
            resulttext = resulttext + "<li>" + item + ":" + str(manuals[item]) +  "\n </li>"
        resulttext += "</p>"
        result = {}
        action = partner_obj.do_partner_print(cr, uid, partner_ids_to_print, data, context=context)
        result['needprinting'] = needprinting
        result['resulttext'] = resulttext
        result['action'] = action or {}
        return result
    
    def do_process(self, cr, uid, ids, context={}):
        
#         get follow-up partners  
        dicPartnerFoll = self._get_partners_followp(cr, uid, ids, context)
        print '+ dicPartnerFoll: ' + str(dicPartnerFoll)
         
        arrPartners = dicPartnerFoll['partner_ids']
        dictAMLs = dicPartnerFoll['to_update']
        dDate = self.browse(cr, uid, ids, context=context)[0].date
        data = self.read(cr, uid, ids, [], context=context)[0]
        
        # update partners
        self.update_partner(cr, uid, ids, dictAMLs, arrPartners, dDate, context=context)
        
        # process partners (sending email,...)
        restot = self.process_partner(cr, uid, arrPartners, data, context=context)
        
        # clear manual actions...
        
        
        res = restot['action']
        #return the next action.
        mod_obj = self.pool.get('ir.model.data')
        model_data_ids = mod_obj.search(cr, uid, [('model','=','ir.ui.view'),('name','=','view_crea8s_followup_send_results')], context=context)
        resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
#       ***** aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *****
        context.update({'description': restot['resulttext'], 'needprinting': restot['needprinting'], 'report_data': res})
        return {
            'name': _('Send Letters and Emails: Actions Summary'),
            'view_type': 'form',
            'context': context,
            'view_mode': 'tree,form',
            'res_model': 'crea8s.followup.send.results',
            'views': [(resource_id,'form')],
            'type': 'ir.actions.act_window',
            'target': 'new',
            }
    
    
    def _get_partners_followp(self, cr, uid, ids, context=None):
        data = {}
        data = self.browse(cr, uid, ids, context=context)[0]
        company_id = data.company_id.id

        cr.execute(
            "SELECT l.partner_id, l.crea8s_followup_line_id,l.date_maturity, l.date, l.id "\
            "FROM account_move_line AS l "\
                "LEFT JOIN account_account AS a "\
                "ON (l.account_id=a.id) "\
            "WHERE (l.reconcile_id IS NULL) "\
#               "AND (a.active) "\
                "AND (a.type='receivable') "\
                "AND (l.partner_id is NOT NULL) "\
                "AND (l.blocked = False) " \
#               "AND (l.debit > 0) "\
                "AND (l.state<>'draft') "\
                "AND (l.company_id = %s) " \
            "ORDER BY l.date", (company_id,))  #l.blocked added to take litigation into account and it is not necessary to change follow-up level of account move lines without debit
        move_lines = cr.fetchall()
        old = None
        fups = {}  
        fup_id = 'followup_id' in context and context['followup_id'] or data.followup_id.id
        dDate = 'date' in context and context['date'] or data.date
 
        current_date = datetime.date(*time.strptime(dDate, '%Y-%m-%d')[:3])
#         current_date = datetime.date(datetime.strptime(date, '%Y-%m-%d')[:3])
        cr.execute(
            "SELECT * "\
            "FROM crea8s_followup_detail "\
            "WHERE crea8s_followup_ref=%s "\
            "ORDER BY delay", (fup_id,))
         
        #Create dictionary of tuples where first element is the date to compare with the due date and second element is the id of the next level
        for result in cr.dictfetchall():
            delay = datetime.timedelta(days=result['delay'])
            fups[old] = (current_date - delay, result['id'])
            old = result['id']
 
        partner_list = []
        to_update = {}
         
        #Fill dictionary of accountmovelines to_update with the partners that need to be updated
        for partner_id, followup_line_id, date_maturity, date, id in move_lines:
            if not partner_id:
                continue
            if followup_line_id not in fups:
                continue
            stat_line_id = partner_id * 10000 + company_id
            if date_maturity:
                if date_maturity <= fups[followup_line_id][0].strftime('%Y-%m-%d'):
                    if stat_line_id not in partner_list:
                        partner_list.append(stat_line_id)
                    to_update[str(id)]= {'level': fups[followup_line_id][1], 'partner_id': stat_line_id}
            elif date and date <= fups[followup_line_id][0].strftime('%Y-%m-%d'):
                if stat_line_id not in partner_list:
                    partner_list.append(stat_line_id)
                to_update[str(id)]= {'level': fups[followup_line_id][1], 'partner_id': stat_line_id}
        return {'partner_ids': partner_list, 'to_update': to_update}
crea8s_followup_send()



class crea8s_followup_send_results(osv.osv):
    _name = "crea8s.followup.send.results"
    _description = 'crea8s.followup.send.results...'
    _columns = {
        
        'description': fields.text('Description', readonly=True),
        'needprinting': fields.boolean('Need printing'),

# 'state': fields.selection([('draft','Draft'),
# ('confirmed','Confirmed')],'State',required=True,readonly=True)
    }
#     _rec_name = 'partner_id'
#     _auto = False # ??? this object is for reporting purpose.
    _default = { 
                'description': 'crea8s_followup_send_results..... asd asd',
                'needprinting': True,
                }
       
    strFormatTime = '%Y-%m-%d %H:%M:%S %Z'   
    def do_report(self, cr, uid, ids, context={}):
       return self.write(cr, uid, ids, {'description': 'printing report !!!'})
    
    def do_done(self, cr, uid, ids, context={}):
       return self.write(cr, uid, ids, {'description': 'done !!!'})
    
crea8s_followup_send_results()



class account_move_line(osv.osv):

    def _get_result_crea8s(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for aml in self.browse(cr, uid, ids, context=context):
            res[aml.id] = aml.debit - aml.credit
        return res

    _inherit = 'account.move.line'
    _columns = {
        'crea8s_followup_line_id': fields.many2one('crea8s.followup.detail', 'Follow-up Level', 
                                        ondelete='restrict'), #restrict deletion of the followup line
        'crea8s_followup_date': fields.date('Latest Follow-up', select=True),
        'crea8s_result': fields.function(_get_result_crea8s, type='float', method=True, 
                                string="Balance") #'balance' field is not the same
    }
    
account_move_line()
    

class crea8s_followup_partner_view(osv.osv): # == account_followup_stat_by_partner

    _name = 'crea8s.followup.partner.view'
    _columns = {
        'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
        'date_move':fields.date('First move', readonly=True),
        'date_move_last':fields.date('Last move', readonly=True),
        'date_followup':fields.date('Latest follow-up', readonly=True),
        'max_followup_detail_id': fields.many2one('crea8s.followup.detail', 'Max Follow Up Level', readonly=True, ondelete="cascade"),
		'debit':fields.float('Debit', readonly=True),
		'credit':fields.float('Credit', readonly=True),
		'balance':fields.float('Balance', readonly=True),
        'company_id': fields.many2one('res.company', 'Company', readonly=True),
        'blocked': fields.boolean('Blocked', readonly=True),
        'period_id': fields.many2one('account.period', 'Period', readonly=True),
        
    }
    _auto = False
#     _rec_name = 'partner_idaaa' #???
    
    def _get_result(self, cr, uid, ids, name, arg, context=None):
    
        return True
    def init(self, cr):
        tools.drop_view_if_exists(cr, 'crea8s_followup_partner_view')
        # Here we don't have other choice but to create a virtual ID based on the concatenation
        # of the partner_id and the company_id, because if a partner is shared between 2 companies,
        # we want to see 2 lines for him in this table. It means that both company should be able
        # to send him follow-ups separately . An assumption that the number of companies will not
        # reach 10 000 records is made, what should be enough for a time.
        cr.execute("""
            create or replace view crea8s_followup_partner_view as (
                SELECT
                    l.partner_id * 10000 + l.company_id as id,
                    l.partner_id AS partner_id,
                    min(l.date) AS date_move,
                    max(l.date) AS date_move_last,
                    max(l.crea8s_followup_date) AS date_followup,
                    max(l.crea8s_followup_line_id) AS max_followup_detail_id,
                    sum(l.debit) AS debit,
                    sum(l.credit) AS credit,
                    sum(l.debit - l.credit) AS balance,
                    l.company_id as company_id,
                    l.blocked as blocked,
                    l.period_id AS period_id
                FROM
                    account_move_line l
                    LEFT JOIN account_account a ON (l.account_id = a.id)
                WHERE
                    a.active AND
                    a.type = 'receivable' AND
                    l.reconcile_id is NULL AND
                    l.partner_id IS NOT NULL AND
                    (l.blocked = False)
                    GROUP BY
                    l.partner_id, l.company_id, l.blocked, l.period_id
            )""") #Blocked is to take into account litigation
        
crea8s_followup_partner_view()
    
    